package com.market.web.model;

import java.awt.Color;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.ResourceBundle;

import javax.faces.context.FacesContext;
import javax.faces.model.SelectItem;

import org.primefaces.model.DefaultStreamedContent;
import org.primefaces.model.StreamedContent;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

import com.itextpdf.text.BadElementException;
import com.itextpdf.text.BaseColor;
import com.itextpdf.text.Chunk;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Element;
import com.itextpdf.text.Font;
import com.itextpdf.text.Image;
import com.itextpdf.text.PageSize;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.Phrase;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.ColumnText;
import com.itextpdf.text.pdf.PdfPTable;
import com.itextpdf.text.pdf.PdfWriter;
import com.market.domain.Product;
import com.market.domain.transients.ReportHeaderFooter;
import com.market.domain.transients.report.OrderDetailSummaryByProduct;

@Component("flyerModel")
@Scope("session")
public class FlyerModel {

	@Autowired
	private ProductModel productModel;

	private Font flyerTitleFont;
	private Font logoTitleFont;
	private Font footerFont;
	private Font productTitleFont;
	private Font productSpecificationFont;
	private Font productRegularPriceFont;
	private Font productSpecialPriceFont;
	private ReportHeaderFooter reportHeaderFooter;
	private PdfWriter pdfWriter;
	private Document document;
	private ByteArrayOutputStream outputStream;

	private void init() {
		outputStream = null;
		try {

			// Initialize fonts;
			BaseFont baseFont = BaseFont.createFont(FacesContext
					.getCurrentInstance().getExternalContext().getRealPath("")
					+ File.separator + "fonts" + File.separator + "SIMSUN.TTF",
					BaseFont.IDENTITY_H, BaseFont.EMBEDDED);

			flyerTitleFont = new Font(baseFont, 15f,
					Font.FontStyle.BOLD.ordinal());
			flyerTitleFont.setColor(BaseColor.RED);

			logoTitleFont = new Font(baseFont, 13f,
					Font.FontStyle.ITALIC.ordinal());
			logoTitleFont.setColor(BaseColor.PINK);

			footerFont = new Font(baseFont, 5f,
					Font.FontStyle.UNDERLINE.ordinal());
			footerFont.setColor(BaseColor.DARK_GRAY);

			productTitleFont = new Font(baseFont, 7f,
					Font.FontStyle.BOLD.ordinal());
			productTitleFont.setColor(BaseColor.BLUE);
			productSpecificationFont = new Font(baseFont, 7f);
			productSpecificationFont.setColor(BaseColor.PINK);
			productRegularPriceFont = new Font(baseFont, 10f);
			productRegularPriceFont.setStyle("line-through");
			productRegularPriceFont.setColor(BaseColor.RED);
			productSpecialPriceFont = new Font(baseFont, 10f,
					Font.FontStyle.BOLD.ordinal());

			productSpecialPriceFont.setColor(BaseColor.GREEN);

			outputStream = new ByteArrayOutputStream();
			document = new Document();
			pdfWriter = PdfWriter.getInstance(document, outputStream);
			Rectangle art = new Rectangle(36f, 18f, 559, 788);
			pdfWriter.setBoxSize("art", art);
			document.setPageSize(PageSize.A4);
			System.out.println(document.getPageSize().getWidth() + ":"
					+ document.getPageSize().getHeight());
			document.setMargins(36f, 36f, 108f, 18f);
			document.open();
			document.add(art);
			pdfWriter.setPageEvent(this.reportHeaderFooter);
		} catch (DocumentException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}

	}

	private void cleanUp() {
		this.productTitleFont = null;
		this.productTitleFont = null;
		try {
			document.close();
		} catch (Exception e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}

		document = null;
		try {
			pdfWriter.close();
		} catch (Exception e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
		pdfWriter = null;
		try {
			outputStream.close();
			outputStream = null;
		} catch (Exception e) {
			outputStream = null;
		}
	}

	public enum LANGUAGE {
		ENGLISH(Locale.ENGLISH), FRENCH(Locale.CANADA_FRENCH), CHINESE(
				Locale.CHINESE);
		Locale locale;

		private LANGUAGE(Locale locale) {
			this.locale = locale;
		}

		public Locale getLocale() {
			return this.locale;
		}

		public String getLabel() {
			java.util.ResourceBundle resBundle = ResourceBundle.getBundle(
					"com.market.messages", this.locale);
			return resBundle.getString("language");
		}
	}

	public List<SelectItem> getAvailableLanguages() {
		List<SelectItem> languages = new ArrayList<SelectItem>();
		for (LANGUAGE language : LANGUAGE.values()) {
			languages.add(new SelectItem(language, language.getLabel()));
		}
		return languages;
	}

	private String title;
	private String validDate;
	private String description;
	private LANGUAGE language = LANGUAGE.ENGLISH;

	public String getTitle() {
		return title;
	}

	public void setTitle(String title) {
		this.title = title;
	}

	public String getValidDate() {
		return validDate;
	}

	public void setValidDate(String validDate) {
		this.validDate = validDate;
	}

	public String getDescription() {
		return description;
	}

	public void setDescription(String description) {
		this.description = description;
	}

	public LANGUAGE getLanguage() {
		return language;
	}

	public void setLanguage(LANGUAGE language) {
		this.language = language;
	}

	public StreamedContent getFlyerPdf() {
		try {
			this.init();

			ColumnText columnText = new ColumnText(
					this.pdfWriter.getDirectContent());

			this.addTitle(columnText);

			float y;
			int status = ColumnText.START_COLUMN;
			int column = 0;

			float[][] productColumn = { { 18, 60, 158, 700 },
					{ 158, 60, 298, 700 }, { 298, 60, 438, 700 },
					{ 438, 60, 578, 700 } };

			columnText.setSimpleColumn(productColumn[column][0],
					productColumn[column][1], productColumn[column][2],
					productColumn[column][3]);
			columnText.setAlignment(Element.ALIGN_CENTER);

			for (Product product : productModel.getSelecteds()) {
				y = columnText.getYLine();

				// columnText.setSimpleColumn(llx, lly, urx, ury);

				// System.out.println(product.getChineseName() + llx + ":" + lly
				// + ":" + urx + ":" + ury);
				try {
					Image icon = Image.getInstance(FacesContext
							.getCurrentInstance().getExternalContext()
							.getRealPath("")
							+ File.separator + product.getIcon() + "128.png");
					icon.scaleToFit(80, 80);
					this.addProduct(columnText, product, icon);
					status = columnText.go(true);

					if (ColumnText.hasMoreText(status)) {
						column++;
						if ((column) % 4 == 0) {
							document.newPage();
							column = 0;
						}
						columnText.setSimpleColumn(productColumn[column][0],
								productColumn[column][1],
								productColumn[column][2],
								productColumn[column][3]);
						y = productColumn[column][3];

					}
					columnText.setYLine(y);
					columnText.setText(null);
					addProduct(columnText, product, icon);
					status = columnText.go(false);
				} catch (MalformedURLException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}

			}

			document.close();
			InputStream input = new ByteArrayInputStream(
					outputStream.toByteArray());
			StreamedContent content = new DefaultStreamedContent(input, "pdf",
					"flyer.pdf");
			return content;
		} catch (DocumentException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
			this.cleanUp();
		}
		return null;
	}

	private void addTitle(ColumnText ct) {
		float[][] titleColumn = { { 18, 700, 150, 788 },
				{ 200, 700, 445, 788 }, { 445, 700, 578, 788 } };
		ct.setSimpleColumn(titleColumn[0][0], titleColumn[0][1],
				titleColumn[0][2], titleColumn[0][3]);

		try {
			Image logo = Image.getInstance(FacesContext.getCurrentInstance()
					.getExternalContext().getRealPath("")
					+ File.separator
					+ "resources"
					+ File.separator
					+ "images"
					+ File.separator + "logo.png");
			logo.scaleToFit(140, 30);
			ct.addElement(logo);
			ct.addElement(new Paragraph("WWW.QuebecFresh.com",
					this.logoTitleFont));
			ct.go(false);

			ct.setSimpleColumn(titleColumn[1][0], titleColumn[1][1],
					titleColumn[1][2], titleColumn[1][3]);
			Paragraph titleParagraph = new Paragraph(this.title,
					this.flyerTitleFont);
			titleParagraph.setAlignment(Element.ALIGN_CENTER
					& Element.ALIGN_MIDDLE);
			ct.addElement(titleParagraph);
			ct.go(false);

			ct.setSimpleColumn(titleColumn[2][0], titleColumn[2][1],
					titleColumn[2][2], titleColumn[2][3]);

			Paragraph footer = new Paragraph(this.getValidDate(),
					this.footerFont);
			footer.setAlignment(Element.ALIGN_RIGHT | Element.ALIGN_BOTTOM);
			ct.addElement(footer);
			ct.go(false);

		} catch (BadElementException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (MalformedURLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (DocumentException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	private void addProduct(ColumnText ct, Product product, Image img)
			throws DocumentException {
		img.setAlignment(Element.ALIGN_CENTER);
		ct.addElement(img);

		Paragraph nameParagraph = new Paragraph(
				product.getNameLabel(this.language.locale),
				this.productTitleFont);
		nameParagraph.add(Chunk.NEWLINE);
		nameParagraph.setAlignment(Element.ALIGN_CENTER);
		ct.addElement(nameParagraph);

		Paragraph specParagraph = new Paragraph(
				product.getSpecificationDescLabel(this.language.locale),
				this.productSpecificationFont);
		specParagraph.setAlignment(Element.ALIGN_CENTER);
		nameParagraph.add(specParagraph);

		if (product.getIsOnSpecial()) {
			Paragraph regularPriceParagraph = new Paragraph("$"
					+ product.getPrice(), this.productRegularPriceFont);
			regularPriceParagraph.setAlignment(Element.ALIGN_CENTER);
			ct.addElement(regularPriceParagraph);
		}

		Paragraph specialPriceParagraph = new Paragraph("$"
				+ product.getSpecialPrice(), this.productSpecialPriceFont);
		specialPriceParagraph.setAlignment(Element.ALIGN_CENTER);
		ct.addElement(specialPriceParagraph);
		ct.addElement(Chunk.NEWLINE);
	}

}
